;(function () {
  //我们来看一个最简单的使用例子：
  type World = 'world'

  // "Hello World"
  type Greeting = `Hello ${World}`

  //! 除了使用确定的类型别名以外，模板字符串类型当然也支持通过泛型参数传入。需要注意的是，并不是所有值都能被作为模板插槽：
  type Greet<T extends string | number | boolean | null | undefined | bigint> = `hello ${T}`

  type Greet1 = Greet<'lys'> // "Hello lys"
  type Greet2 = Greet<599> // "Hello 599"
  type Greet3 = Greet<true> // "Hello true"
  type Greet4 = Greet<null> // "Hello null"
  type Greet5 = Greet<undefined> // "Hello undefined"
  type Greet6 = Greet<0x1fffffffffffff> // "Hello 9007199254740991"

  //目前有效的类型只有 string | number | boolean | null | undefined | bigint 这几个。正如上面的例子所示，这些类型在最终的字符串结果中都会被转换为字符串字面量类型，即使是 null 与 undefined。

  //你也可以直接为插槽传入一个类型而非类型别名：
  type greeting = `hello ${string}`
  //在这种情况下，Greeting 类型并不会变成 Hello string，而是保持原样。这也意味着它并没有实际意义，此时就是一个无法改变的模板字符串类型，但所有 Hello 开头的字面量类型都会被视为 Hello ${string} 的子类型，如 Hello Linbudu、Hello TypeScript 。
  type Version = `${number}.${number}.${number}`

  const v1: Version = '1.1.0'
  // X 类型 "1.0" 不能赋值给类型 `${number}.${number}.${number}`
  // const v2: Version = '1.0'

  //模板字符串类型也能在减少代码的同时获得更好的类型保障。举例来说，当我们需要声明以下字符串类型时：
  type SKU =
    | 'iphone-16G-official'
    | 'xiaomi-16G-official'
    | 'honor-16G-official'
    | 'iphone-16G-second-hand'
    | 'xiaomi-16G-second-hand'
    | 'honor-16G-second-hand'
    | 'iphone-64G-official'
    | 'xiaomi-64G-official'
    | 'honor-64G-official'
    | 'iphone-64G-second-hand'
    | 'xiaomi-64G-second-hand'
    | 'honor-64G-second-hand'

  //随着商品、内存数、货品类型的增加，我们可能需要成几何倍地新增。但如果使用模板字符串类型，我们可以利用其自动分发的特性来实现简便而又严谨的声明：
  type Brand = 'iphone' | 'xiaomi' | 'honor'
  type Memory = '16G' | '64G'
  type ItemType = 'official' | 'second-hand'

  type SKU_String_struct = `${Brand}-${Memory}-${ItemType}` // 可以看到自动组合 完毕了

  type SKU_test = SKU extends SKU_String_struct ? 1 : 2

  //$除了直接在插槽中传递联合类型，通过泛型传入联合类型时同样会有分发过程：
  type SizeRecord<Size extends string> = `${Size}-record`

  type Size = 'Small' | 'Middle' | 'Large'

  type UnionSizeRecord = SizeRecord<Size> //"Small-record" | "Middle-record" | "Large-record"
})()
// # 模板字符串类型的类型表现
declare let v1: `${number}.${number}.${number}`
declare let v2: '1.2.4'
v1 = v2
// 如果反过来，v2 = v1 很显然是不成立的，因为 v1 还包含了 100.0.0 等等情况。
// v2 = v1

const greet = (to: string): `Hello ${string}` => {
  return `Hello ${to}`
}
